package vaadin.lab8;

import java.util.Arrays;
import java.util.Date;

import com.vaadin.Application;
import com.vaadin.data.Container;
import com.vaadin.data.Container.Filter;
import com.vaadin.data.Item;
import com.vaadin.data.Property;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.util.filter.And;
import com.vaadin.data.util.filter.Compare;
import com.vaadin.lab7.ProductFieldFactory;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Component;
import com.vaadin.ui.DateField;
import com.vaadin.ui.Form;
import com.vaadin.ui.FormLayout;
import com.vaadin.ui.GridLayout;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Layout;
import com.vaadin.ui.PopupDateField;
import com.vaadin.ui.Table;
import com.vaadin.ui.Window;

@SuppressWarnings("serial")
public class Lab extends Application {

    private Container.Filterable container;
    private DateField startDate;
    private DateField endDate;

    @Override
    public void init() {
        GridLayout mainLayout = new GridLayout(2, 2);
        mainLayout.setSizeFull();
        Window mainWindow = new Window("Lab", mainLayout);
        setMainWindow(mainWindow);

        FormLayout formLayout = new FormLayout();
        formLayout.setMargin(true);
        final Form form = new Form(formLayout);
        form.setFormFieldFactory(new ProductFieldFactory());
        form.setImmediate(true);

        container = ContainerHelper.createProductContainer();
        final Table productTable = new Table("Products", container);
        productTable.setImmediate(true);
        productTable.setSelectable(true);
        productTable.setWidth("100%");
        productTable.addListener(new Property.ValueChangeListener() {

            @Override
            public void valueChange(ValueChangeEvent event) {
                Object id = event.getProperty().getValue();
                form.setItemDataSource(productTable.getItem(id),
                        Arrays.asList(ProductFieldFactory.PRODUCT_FIELD_ORDER));
            }
        });

        mainLayout.addComponent(createFilterComponents(), 0, 0, 1, 0);
        mainLayout.setRowExpandRatio(1, 1.0f);
        mainLayout.addComponent(productTable);
        mainLayout.addComponent(form);
    }

    private Layout createFilterComponents() {
        HorizontalLayout layout = new HorizontalLayout();
        layout.setSpacing(true);

        startDate = new PopupDateField("Start");
        startDate.setResolution(DateField.RESOLUTION_DAY);

        endDate = new PopupDateField("End");
        endDate.setResolution(DateField.RESOLUTION_DAY);

        layout.addComponent(startDate);
        layout.addComponent(endDate);

        Component filterButton = new Button("Filter",
                new Button.ClickListener() {
                    @Override
                    public void buttonClick(ClickEvent event) {
                        container.removeAllContainerFilters();
                        container.addContainerFilter(new DateRangeFilter(
                                (Date) startDate.getValue(), (Date) endDate
                                        .getValue()));
                    }
                });
        layout.addComponent(filterButton);
        layout.setComponentAlignment(filterButton, Alignment.BOTTOM_LEFT);

        return layout;
    }

    private static class DateRangeFilter implements Filter {

        private final Filter wrappedFilter;

        public DateRangeFilter(Date startDate, Date endDate) {
            wrappedFilter = new And(new Compare.GreaterOrEqual("available",
                    startDate), new Compare.LessOrEqual("available", endDate));
        }

        @Override
        public boolean passesFilter(Object itemId, Item item)
                throws UnsupportedOperationException {
            return wrappedFilter.passesFilter(itemId, item);
        }

        @Override
        public boolean appliesToProperty(Object propertyId) {
            return wrappedFilter.appliesToProperty(propertyId);
        }
    }
}
